home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / ispell40.lha / ispell-4.0 / screen.c < prev    next >
C/C++ Source or Header  |  1993-05-31  |  19KB  |  956 lines

  1. /* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  2.  
  3.    This file is part of GNU ISPELL.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <setjmp.h>
  23. #include <signal.h>
  24. #include "ispell.h"
  25. #include "hash.h"
  26.  
  27. int reading_interactive_command;
  28. jmp_buf command_loop;
  29.  
  30. extern struct sp_corrections corrections;
  31.  
  32. #ifdef __STDC__
  33. static void copyout (char **, int, FILE *);
  34. #else
  35. static void copyout ();
  36. #endif
  37.  
  38. extern int lflag;
  39. extern int uflag;
  40. extern int iflag;
  41. extern FILE *sortf;
  42. extern int Sflag;
  43. extern int intr_typed;
  44.  
  45. char tempfile[100];
  46.  
  47. #define NOPARITY 0x7f
  48.  
  49. static void
  50. giveihelp ()
  51. {
  52.   erase ();
  53.   printf ("You have interrupted ISPELL.  Commands are:\r\n");
  54.   printf ("\r\n");
  55.   printf ("SPACE    Continue scanning the current file.\r\n");
  56.   printf ("Q        Write changes so far, and ignore misspellings in\r\n");
  57.   printf ("             the rest of the file.\r\n");
  58.   printf ("X        Abandon changes to this file.\r\n");
  59.   printf ("!       Shell escape.\r\n");
  60.   printf ("^L      Redraw screen.\r\n");
  61.   printf ("\r\n\r\n");
  62.   printf ("-- Type space to continue --");
  63.   fflush (stdout);
  64.   getchar ();
  65. }
  66.  
  67. static void
  68. givehelp ()
  69. {
  70.   erase ();
  71.   (void) printf ("Whenever a word is found that is not in the dictionary,\r\n");
  72.   (void) printf ("it is printed on the first line of the screen.  If the dictionary\r\n");
  73.   (void) printf ("contains any similar words, they are listed with a single digit\r\n");
  74.   (void) printf ("next to each one.  You have the option of replacing the word\r\n");
  75.   (void) printf ("completely, or choosing one of the suggested words.\r\n");
  76.   (void) printf ("\r\n");
  77.   (void) printf ("Commands are:\r\n\r\n");
  78.   (void) printf ("R       Replace the misspelled word completely.\r\n");
  79.   (void) printf ("Space   Accept the word this time only\r\n");
  80.   (void) printf ("A       Accept the word for the rest of this file.\r\n");
  81.   (void) printf ("I       Accept the word, and put it in your private dictionary.\r\n");
  82.   (void) printf ("0-9     Replace with one of the suggested words.\r\n");
  83.   (void) printf ("<NL>    Recompute near misses.  Use this if you interrupted\r\n");
  84.   (void) printf ("             the near miss generator, and you want it to\r\n");
  85.   (void) printf ("             again on this word.\r\n");
  86.   (void) printf ("Q       Write the rest of this file, ignoring misspellings,\r\n");
  87.   (void) printf ("            and start next file.\r\n");
  88.   (void) printf ("X       Exit immediately.  Asks for conformation.\r\n");
  89.   (void) printf ("            Leaves file unchanged.\r\n");
  90.   (void) printf ("!       Shell escape.\r\n");
  91.   (void) printf ("^L      Redraw screen.\r\n");
  92.   (void) printf ("\r\n\r\n");
  93.   (void) printf ("-- Type space to continue --");
  94.   (void) fflush (stdout);
  95.   (void) getchar ();
  96. }
  97.  
  98.  
  99. char *getline ();
  100.  
  101. char firstbuf[BUFSIZ], secondbuf[BUFSIZ];
  102. char gtoken[BUFSIZ + 10];
  103.  
  104. int quit;
  105.  
  106. char *currentfile = NULL;
  107. static long filesize;
  108. static FILE *filestream;
  109.  
  110. int changed;
  111.  
  112. void
  113. dofile (filename)
  114.   char *filename;
  115. {
  116.   int c;
  117.   FILE *in, *out;
  118.   void (*oldf) (NOARGS);
  119.  
  120.   currentfile = filename;
  121.  
  122.   if ((in = fopen (filename, "r")) == NULL)
  123.     {
  124.       (void) fprintf (stderr, "Can't open %s\r\n", filename);
  125.       return;
  126.     }
  127.  
  128.   changed = 0;
  129.  
  130.   filesize = lseek (fileno (in), 0l, 2);
  131.   (void) lseek (fileno (in), 0l, 0);
  132.  
  133.   if (access (filename, 2) < 0)
  134.     {
  135.       (void) fprintf (stderr, "Can't write to %s\r\n", filename);
  136.       return;
  137.     }
  138.  
  139.   (void) strcpy (tempfile, "/usr/tmp/ispellXXXXXX");
  140.   (void) mktemp (tempfile);
  141.   if ((out = fopen (tempfile, "w")) == NULL)
  142.     {
  143.       (void) fprintf (stderr, "Can't create %s\r\n", tempfile);
  144.       return;
  145.     }
  146.  
  147.   quit = 0;
  148.  
  149.   checkfile (in, out, (long) 0);
  150.  
  151.   (void) fclose (in);
  152.   (void) fclose (out);
  153.  
  154.   if (changed == 0)
  155.     {
  156.       (void) unlink (tempfile);
  157.       tempfile[0] = 0;
  158.       return;
  159.     }
  160.  
  161.   if ((in = fopen (tempfile, "r")) == NULL)
  162.     {
  163.       (void) fprintf (stderr, "tempoary file disappeared (%s)\r\n", tempfile);
  164.       (void) sleep (2);
  165.       return;
  166.     }
  167.  
  168.   oldf = (void (*)(NOARGS)) signal (SIGINT, SIG_IGN);
  169.  
  170.   if ((out = fopen (filename, "w")) == NULL)
  171.     {
  172.       (void) unlink (tempfile);
  173.       tempfile[0] = 0;
  174.       (void) fprintf (stderr, "can't create %s\r\n", filename);
  175.       (void) sleep (2);
  176.       return;
  177.     }
  178.  
  179.   while ((c = getc (in)) != EOF)
  180.     putc (c, out);
  181.  
  182.   fclose (in);
  183.   (void) fclose (out);
  184.  
  185.   (void) unlink (tempfile);
  186.   tempfile[0] = 0;
  187.  
  188.   signal (SIGINT, (RETSIGTYPE (*)()) oldf);
  189. }
  190.  
  191. char *currentchar;
  192. FILE *out;
  193.  
  194.  
  195. void
  196. checkfile (in, outx, end)
  197.      FILE *in, *outx;
  198.      long end;
  199. {
  200.   char *p;
  201.   int maybe_troff;
  202.   char *cstart, *cend;
  203.   int i;
  204.   long lineoffset;
  205.  
  206.   out = outx;
  207.  
  208. checkstart:
  209.   filestream = in;
  210.   secondbuf[0] = 0;
  211.  
  212.   maybe_troff = 0;
  213.   while (1)
  214.     {
  215.       (void) strcpy (firstbuf, secondbuf);
  216.       if (quit)
  217.     {
  218.       if (out == NULL)
  219.         return;
  220.       while (fgets (secondbuf, sizeof secondbuf, in)
  221.          != NULL)
  222.         (void) fputs (secondbuf, out);
  223.       break;
  224.     }
  225.  
  226.       if (Sflag)
  227.     {
  228.       lineoffset = ftell (in);
  229.       if (end && lineoffset >= end)
  230.         break;
  231.     }
  232.       if (fgets (secondbuf, sizeof secondbuf, in) == NULL)
  233.     break;
  234.  
  235.       /* uflag is on when emulating traditional spell
  236.          * if so, then follow troff commands '.so' and '.nx'
  237.          */
  238.       if (uflag && !iflag && secondbuf[0] == '.')
  239.     {
  240.       int soflag = 0, nxflag = 0;
  241.       FILE *so;
  242.       char *n, *end;
  243.       if (strncmp (secondbuf, ".so", 3) == 0)
  244.         soflag = 1;
  245.       if (strncmp (secondbuf, ".nx", 3) == 0)
  246.         nxflag = 1;
  247.       if (soflag || nxflag)
  248.         {
  249.           n = secondbuf + 3;
  250.           while (isspace (*n))
  251.         n++;
  252.           end = n;
  253.           while (*end && !isspace (*end))
  254.         end++;
  255.           *end = 0;
  256.           if (strncmp (n, "/usr/lib", 8) == 0)
  257.         continue;
  258.           if (nxflag)
  259.         {
  260.           if (freopen (n, "r", in) == NULL)
  261.             {
  262.               (void) fprintf (stderr, "can't open %s\n",
  263.                       n);
  264.               return;
  265.             }
  266.           goto checkstart;
  267.         }
  268.           if ((so = fopen (n, "r")) == NULL)
  269.         {
  270.           (void) fprintf (stderr,
  271.                   "can't open %s\n", n);
  272.         }
  273.           else
  274.         {
  275.           /* FIXME: gcc -Wall found the third argument missing in this call
  276.            to checkfile. The function isn't documented, so I have no idea what
  277.            it actually is supposed flag. My assumption is that it worked in most
  278.            instances because random junk on the stack would likely be non-zero.
  279.            --bson */
  280.  
  281.           checkfile (so, (FILE *) NULL, (long) 1);
  282.           (void) fclose (so);
  283.         }
  284.           continue;
  285.         }
  286.     }
  287.  
  288.       currentchar = secondbuf;
  289.  
  290.       p = secondbuf + strlen (secondbuf) - 1;
  291.       if (*p == '\n')
  292.     *p = 0;
  293.  
  294.       while (1)
  295.     {
  296.       if (skip_to_next_word (out) == 0)
  297.         break;
  298.       cstart = currentchar;
  299.       cend = cstart;
  300.       if (intr_typed)
  301.         {
  302.           if (lflag || Sflag)
  303.         return;
  304.  
  305.           gtoken[0] = 0;
  306.           (void) correct (gtoken, sizeof gtoken,
  307.                   cstart, cend, ¤tchar);
  308.           if (quit)
  309.         {
  310.           (void) fputs (currentchar, out);
  311.           break;
  312.         }
  313.           intr_typed = 0;
  314.         }
  315.  
  316.       /* first letter is a lexletter, therefore,
  317.              * loop will execute at least once
  318.              */
  319.       p = gtoken;
  320.       i = 0;
  321.       while (islexletter (*cend) && i < MAX_WORD_LEN - 5)
  322.         {
  323.           *p++ = *cend++;
  324.           i++;
  325.         }
  326.       /* flush quote if at end of word */
  327.       if (p[-1] == '\'')
  328.         {
  329.           p--;
  330.           cend--;
  331.         }
  332.       *p = 0;
  333.  
  334.       currentchar = cend;
  335.  
  336.       if (good (gtoken, strlen (gtoken), 0))
  337.         {
  338.           if (out)
  339.         (void) fputs (gtoken, out);
  340.           continue;
  341.         }
  342.       interaction_flag = 1;
  343.       /* word is bad */
  344.       if (uflag)
  345.         {
  346.           /* traditional spell compatability */
  347.           (void) fputs (gtoken, sortf);
  348.           (void) putc ('\n', sortf);
  349.           /* don't report this word again by doing 'A' */
  350.           (void) p_enter (gtoken, 2, 0);
  351.           continue;
  352.         }
  353.       if (lflag)
  354.         {
  355.           /* make a simple list of bad words */
  356.           (void) puts (gtoken);
  357.           (void) p_enter (gtoken, 1, 0);
  358.           continue;
  359.         }
  360.       if (Sflag)
  361.         {
  362.           /* program interface */
  363.           (void) printf ("%ld\n", lineoffset + (cstart - secondbuf));
  364.           continue;
  365.         }
  366.       /* interactive mode */
  367.       if (correct (gtoken, sizeof gtoken,
  368.                cstart, cend, ¤tchar))
  369.         {
  370.           /* user accepted, or choose a near miss */
  371.           (void) fputs (gtoken, out);
  372.           if (quit)
  373.         {
  374.           (void) fputs (currentchar, out);
  375.           break;
  376.         }
  377.         }
  378.       else
  379.         {
  380.           /* user typed replacement, rescan */
  381.           currentchar = cstart;
  382.         }
  383.     }
  384.       if (out)
  385.     (void) putc ('\n', out);
  386.     }
  387. }
  388.  
  389. /* return 0 if no more words on this line
  390.  * else return 1
  391.  */
  392. int
  393. skip_to_next_word (out)
  394.   FILE *out;
  395. {
  396.   switch (formatter)
  397.     {
  398.     case formatter_troff:
  399.       return (skip_to_next_word_troff ());
  400.     case formatter_tex:
  401.       return (skip_to_next_word_tex (out));
  402.     case formatter_generic:
  403.     default:
  404.       return (skip_to_next_word_generic ());
  405.     }
  406. }
  407.  
  408. int
  409. skip_to_next_word_generic ()
  410. {
  411.   if (currentchar == secondbuf)
  412.     {
  413.       /* at beginning of line */
  414.       if (*currentchar == '.')
  415.     {
  416.       formatter = formatter_troff;
  417.       skip_to_next_word_troff ();
  418.  
  419.       /* FIXME:
  420.          gcc -Wall found the argument missing. What is the return value supposed to
  421.          indicate? It used to just say "return;" --bson */
  422.       return 1;
  423.     }
  424.     }
  425.  
  426.   while (*currentchar)
  427.     {
  428.       /* skip any leading apostrophes */
  429.       if (islexletter (*currentchar) && *currentchar != '\'')
  430.     return (1);
  431.       copyout (¤tchar, 1, out);
  432.     }
  433.   return (0);
  434. }
  435.  
  436. int
  437. skip_to_next_word_troff ()
  438. {
  439.   if (currentchar == secondbuf)
  440.     {
  441.       /* at beginning of line */
  442.       /* if this is a formatter command, skip the line */
  443.       if (*currentchar == '.')
  444.     {
  445.       if (out)
  446.         {
  447.           while (*currentchar)
  448.         (void) putc (*currentchar++, out);
  449.         }
  450.       return (0);
  451.     }
  452.     }
  453.  
  454.   while (*currentchar)
  455.     {
  456.       if (islexletter (*currentchar) && *currentchar != '\'')
  457.     return (1);
  458.  
  459.       if (*currentchar != '\\')
  460.     {
  461.       copyout (¤tchar, 1, out);
  462.       continue;
  463.     }
  464.  
  465.       if (currentchar[1] == 'f')
  466.     {
  467.       /* \fB or \f(XY */
  468.       if (currentchar[2] == '(')
  469.         copyout (¤tchar, 5, out);
  470.       else
  471.         copyout (¤tchar, 3, out);
  472.     }
  473.       else if (currentchar[1] == 's')
  474.     {
  475.       /* \s5 \s+2 \s-2 \s30
  476.              * skip one following character
  477.              * there may be more digits following, but
  478.              * they will get skipped since they are not
  479.              * lexletters
  480.              */
  481.       copyout (¤tchar, 3, out);
  482.     }
  483.       else if (currentchar[1] == '(')
  484.     {
  485.       /* extended character set \(XY */
  486.       copyout (¤tchar, 3, out);
  487.     }
  488.       else if (currentchar[1] == '*')
  489.     {
  490.       /* string interpolation \*X \*(XY */
  491.       if (currentchar[2] == '(')
  492.         copyout (¤tchar, 5, out);
  493.       else
  494.         copyout (¤tchar, 3, out);
  495.     }
  496.       else
  497.     {
  498.       copyout (¤tchar, 1, out);
  499.     }
  500.     }
  501.  
  502.   return (0);
  503. }
  504.  
  505. /* return 1 if everyting ok, 0 to recheck some */
  506. int
  507. correct (token, toksiz, start, end, pcurrentchar)
  508.   char *token;
  509.   unsigned toksiz;
  510.   char *start, *end;
  511.   char **pcurrentchar;
  512. {
  513.   int c;
  514.   int i;
  515.   char *p;
  516.   int len;
  517.   int needposs;
  518.   int intcnt = 0;
  519.   int mpinterrupted = 0;
  520.  
  521.  
  522.   /* zero length token just means to run the command loop */
  523.   len = strlen (token);
  524.  
  525.   needposs = 1;
  526.   corrections.nwords = 0;
  527. redraw:
  528.   (void) setjmp (command_loop);
  529.  
  530.   erase ();
  531.   if (len)
  532.     {
  533.       (void) printf ("    %s", token);
  534.     }
  535.   else
  536.     {
  537.       inverse ();
  538.       (void) printf ("(INTERRUPT)");
  539.       normal ();
  540.       needposs = 0;
  541.     }
  542.  
  543.   if (currentfile)
  544.     (void) printf ("              File: %s (%ld%%)", currentfile,
  545.            ftell (filestream) * 100 / filesize);
  546.   (void) printf ("\r\n\r\n");
  547.  
  548.   if (needposs)
  549.     {
  550.       mpinterrupted = makepossibilities (token);
  551.       needposs = 0;
  552.     }
  553.   for (i = 0; i < corrections.nwords; i++)
  554.     {
  555.       if (corrections.posbuf[i][0] == 0)
  556.     break;
  557.       (void) printf ("%d: %s\r\n", i, corrections.posbuf[i]);
  558.     }
  559.   if (mpinterrupted)
  560.     (void) printf ("(near miss generator interrupted; type return to rerun)\r\n");
  561.  
  562.   move (15, 0);
  563.   (void) printf ("%s\r\n", firstbuf);
  564.  
  565.   for (p = secondbuf; p != start; p++)
  566.     (void) putchar (*p);
  567.   inverse ();
  568.   for (i = len; i > 0; i--)
  569.     (void) putchar (*p++);
  570.   normal ();
  571.   while (*p)
  572.     (void) putchar (*p++);
  573.   (void) printf ("\r\n");
  574.  
  575.   while (1)
  576.     {
  577.       (void) fflush (stdout);
  578.       intr_typed = 0;
  579.       reading_interactive_command = 1;
  580.       c = getchar ();
  581.       reading_interactive_command = 0;
  582.       if (c == -1)
  583.     {
  584.       intcnt++;
  585.       if (intcnt == 10)
  586.         {
  587.           quit = 1;
  588.           erase ();
  589.           return (1);
  590.         }
  591.       goto redraw;
  592.     }
  593.       intcnt = 0;
  594.       c &= NOPARITY;
  595.       switch (c)
  596.     {
  597.     case '\r':
  598.     case '\n':
  599.       if (len)
  600.         needposs = 1;
  601.       goto redraw;
  602.     case 'Z' & 037:
  603.     case 'Y' & 037:
  604.     case 'Z':
  605.       stop ();
  606.       goto redraw;
  607.     case ' ':        /* accept this time only */
  608.       erase ();
  609.       return 1;
  610.     case 'x':
  611.     case 'X':        /* exit without writing */
  612.       (void) printf ("Exit without writing changes? ");
  613.       (void) fflush (stdout);
  614.       c = (getchar () & NOPARITY);
  615.       if (c == 'y' || c == 'Y')
  616.         {
  617.           erase ();
  618.           done ();
  619.         }
  620.       termbeep ();
  621.       goto redraw;
  622.     case 'i':
  623.     case 'I':        /* put in private dictionary */
  624.       if (len == 0)
  625.         break;
  626.       if (len < MAX_WORD_LEN - 5)
  627.         (void) p_enter (token, 1, 1);
  628.       erase ();
  629.       return 1;
  630.     case 'a':
  631.     case 'A':        /* don't report again this session */
  632.       if (len == 0)
  633.         break;
  634.       if (len < MAX_WORD_LEN - 5)
  635.         (void) p_enter (token, 1, 0);
  636.       erase ();
  637.       return 1;
  638.     case 'L' & 037:    /* redraw */
  639.       goto redraw;
  640.     case '?':        /* help */
  641.       if (len == 0)
  642.         giveihelp ();
  643.       else
  644.         givehelp ();
  645.       goto redraw;
  646.     case '!':
  647.       {
  648.         char buf[200];
  649.         move (18, 0);
  650.         (void) putchar ('!');
  651.         if (getline (buf, sizeof buf) == NULL)
  652.           goto redraw;
  653.         (void) printf ("\r\n");
  654.         shellescape (buf);
  655.         goto redraw;
  656.       }
  657.     case 'r':
  658.     case 'R':
  659.       if (len == 0)
  660.         break;
  661.       move (18, 0);
  662.       (void) printf ("Replace with: ");
  663.       if (getline (token, toksiz) == NULL)
  664.         goto redraw;
  665.       inserttoken (secondbuf, start, end, token, (char **) NULL);
  666.       erase ();
  667.       return 0;        /* 0 means rescan */
  668.     case 'l':
  669.     case 'L':
  670.       move (18, 0);
  671.       (void) printf ("Lookup (regular expression): ");
  672.       if (getline (token, toksiz) == NULL)
  673.         goto redraw;
  674.       move (19, 0);
  675.       termflush ();
  676.       dolook_interactive (token);
  677.       goto redraw;
  678.     case '0':
  679.     case '1':
  680.     case '2':
  681.     case '3':
  682.     case '4':
  683.     case '5':
  684.     case '6':
  685.     case '7':
  686.     case '8':
  687.     case '9':
  688.       if (corrections.posbuf[c - '0'][0] != 0)
  689.         {
  690.           (void) strcpy (token, corrections.posbuf[c - '0']);
  691.           inserttoken (secondbuf, start, end, token,
  692.                pcurrentchar);
  693.           erase ();
  694.           return 1;
  695.         }
  696.       break;
  697.     case 'q':
  698.     case 'Q':
  699.       quit = 1;
  700.       erase ();
  701.       return 1;
  702.     default:
  703.       break;
  704.     }
  705.       termbeep ();
  706.     }
  707. }
  708.  
  709. /*
  710.  * buf is line
  711.  * replace between start and end with token
  712.  */
  713. void
  714. inserttoken (buf, start, end, token, pcurrentchar)
  715.   char *buf, *start, *end, *token;
  716.   char **pcurrentchar;
  717. {
  718.   char copy[BUFSIZ];
  719.   char *p, *q;
  720.  
  721.   changed = 1;
  722.  
  723.   /* copy up to start */
  724.   for (p = copy, q = buf; q != start; p++, q++)
  725.     *p = *q;
  726.   /* put in token */
  727.   while (*token)
  728.     *p++ = *token++;
  729.   /* remember place in buf */
  730.   if (pcurrentchar)
  731.     *pcurrentchar = buf + (p - copy);
  732.   /* skip over old stuff */
  733.   q = end;
  734.   /* copy the tail of the line */
  735.   while (*q)
  736.     *p++ = *q++;
  737.   *p = 0;
  738.   (void) strcpy (buf, copy);
  739. }
  740.  
  741. char *
  742. getline (s, siz)
  743.   char *s;
  744.   unsigned siz;
  745. {
  746.   char *p;
  747.   int c;
  748.   extern int erasechar, killchar;
  749.   int pos;
  750.  
  751.   if (siz <= 1)
  752.     return (NULL);
  753.   siz--;
  754.   p = s;
  755.   pos = 0;
  756.  
  757.   while (1)
  758.     {
  759.       c = (getchar () & NOPARITY);
  760.       if (c == '\\')
  761.     {
  762.       if (pos == siz)
  763.         {
  764.           p--;
  765.           pos--;
  766.           backup ();
  767.         }
  768.       (void) putchar ('\\');
  769.       c = (getchar () & NOPARITY);
  770.       backup ();
  771.       (void) putchar (c);
  772.       *p++ = c;
  773.       pos++;
  774.     }
  775.       else if (c == ('G' & 037))
  776.     {
  777.       return (NULL);
  778.     }
  779.       else if (c == '\n' || c == '\r')
  780.     {
  781.       *p = 0;
  782.       return (s);
  783.     }
  784.       else if (c == erasechar)
  785.     {
  786.       if (p != s)
  787.         {
  788.           p--;
  789.           backup ();
  790.           (void) putchar (' ');
  791.           backup ();
  792.         }
  793.     }
  794.       else if (c == killchar)
  795.     {
  796.       while (p != s)
  797.         {
  798.           p--;
  799.           backup ();
  800.           (void) putchar (' ');
  801.           backup ();
  802.         }
  803.     }
  804.       else
  805.     {
  806.       if (pos == siz)
  807.         {
  808.           p--;
  809.           pos--;
  810.           backup ();
  811.         }
  812.       *p++ = c;
  813.       (void) putchar (c);
  814.     }
  815.     }
  816. }
  817.  
  818.  
  819. void
  820. askmode (verbose)
  821.   int verbose;
  822. {
  823.   char buf[MAX_WORD_LEN];
  824.   int i;
  825.   int len;
  826.  
  827.   setbuf (stdin, (char *) NULL);
  828.   setbuf (stdout, (char *) NULL);
  829.  
  830.   while (1)
  831.     {
  832.       if (verbose)
  833.     {
  834.       (void) printf ("word: ");
  835.       (void) fflush (stdout);
  836.     }
  837.  
  838.       if (fgets (buf, MAX_WORD_LEN - 5, stdin) == NULL)
  839.     break;
  840.  
  841.       len = strlen (buf);
  842.       if (len && buf[len - 1] == '\n')
  843.     buf[--len] = 0;
  844.  
  845.       if (verbose && len == 0)
  846.     continue;
  847.  
  848.       if (good (buf, strlen (buf), 0))
  849.     {
  850.       /* used to print + if rootword */
  851.       if (verbose)
  852.         (void) printf ("ok\n");
  853.       else
  854.         (void) printf ("*\n");
  855.     }
  856.       else
  857.     {
  858.       (void) makepossibilities (buf);
  859.       if (corrections.posbuf[0][0])
  860.         {
  861.           if (verbose)
  862.         (void) printf ("how about: ");
  863.           else
  864.         (void) printf ("& ");
  865.           for (i = 0; i < 10; i++)
  866.         {
  867.           if (corrections.posbuf[i][0] == 0)
  868.             break;
  869.           (void) printf ("%s ",
  870.                  corrections.posbuf[i]);
  871.         }
  872.           (void) printf ("\n");
  873.         }
  874.       else
  875.         {
  876.           if (verbose)
  877.         (void) printf ("not found\n");
  878.           else
  879.         (void) printf ("#\n");
  880.         }
  881.     }
  882.     }
  883. }
  884.  
  885. static void
  886. copyout (cc, cnt, out)
  887.   char **cc;
  888.   int cnt;
  889.   FILE *out;
  890. {
  891.   while (--cnt >= 0)
  892.     {
  893.       if (*(*cc) == 0)
  894.     break;
  895.       if (out)
  896.     (void) putc (*(*cc), out);
  897.       (*cc)++;
  898.     }
  899. }
  900.  
  901. static char *lookcmd, *lookarg1, *lookarg2;
  902.  
  903. /* this runs in a child with the terminal set back to normal
  904.  * and with the parent ignoring signals
  905.  */
  906. void
  907. lookfun (NOARGS)
  908. {
  909.   if (lookarg2 == NULL)
  910.     (void) execlp (lookcmd, lookcmd, lookarg1, NULL);
  911.   else
  912.     (void) execlp (lookcmd, lookcmd, lookarg1, lookarg2, NULL);
  913. }
  914.  
  915.  
  916. void
  917. dolook (str)
  918.      char *str;
  919. {
  920.   char *p;
  921.   int wild = 0;
  922.  
  923.   for (p = str; *p; p++)
  924.     {
  925.       if (strchr (".*[\\", *p) != NULL)
  926.     wild = 1;
  927.       if (isupper (*p))
  928.     *p = tolower (*p);
  929.     }
  930.  
  931.   if (wild == 0)
  932.     {
  933.       lookcmd = "look";
  934.       lookarg1 = str;
  935.       lookarg2 = NULL;
  936.       if (!dochild (lookfun))
  937.     return;
  938.     }
  939.  
  940.   lookcmd = "egrep";
  941.   lookarg1 = str;
  942.   lookarg2 = "/usr/lib/ispell.words";
  943.   dochild (lookfun);
  944. }
  945.  
  946.  
  947. void
  948. dolook_interactive (str)
  949.   char *str;
  950. {
  951.  
  952.   dolook (str);
  953.   (void) printf ("\n-- Type space to continue --");
  954.   (void) getchar ();
  955. }
  956.